home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 5 / Apprentice-Release5.iso / Source Code / C++ / Snippets / CMIO / CMIO.cpp next >
Encoding:
C/C++ Source or Header  |  1994-10-12  |  7.6 KB  |  277 lines  |  [TEXT/R*ch]

  1. /*********************************************************************\
  2.  
  3.     CMIO.cpp
  4.     
  5.     [Macintosh]
  6.     
  7.     Routines for doing A/D conversion with National Instruments
  8.     NB-MIO-16 card.
  9.     Written by Dan Crevier, 1994
  10.     
  11.     Usage:
  12.         At startup:
  13.         • Create a CMIO object (myMIO = new CMIO)
  14.         • Call Config().  It will return true if there is an MIO
  15.             board available, false if there isn't
  16.  
  17.         Each time you want to record some data:
  18.         • Call ConfigureCollection() with the array of channels
  19.             to scan, the interval in µs between samples, and
  20.             the number of samples to record
  21.         • Call StartCollection() to start the data collection
  22.         • Call SampleAvailable() to see if a sample is available
  23.             It can also return error codes kErrOverflow, kErrOverrun
  24.             (or kErrOverflow + kOverrun).  These are described on
  25.             page 4-53 in the NB-MIO-16 User's manual (amoung other
  26.             places)
  27.         • Call GetSample() to return the sample.  It will be in
  28.             signed format
  29.  
  30. \*********************************************************************/
  31.  
  32. #include <slots.h>
  33. #include <string.h>
  34. #include "CMIO.h"
  35.  
  36. #define macSlotNum(s) (s+8)        /* slot translation */
  37. #define GetBase24Address(s) (((long) (macSlotNum(s))) << 20)
  38. #define GetBase32Address(s) ((((long) (macSlotNum(s))) << 24) | 0xF0000000)
  39.  
  40. // Make sure it doesn't optimize out any code that looks useless, like
  41. // writing different values to an MIO register in two consequtive
  42. // statements
  43.  
  44. #pragma options(!global_optimizer)
  45.  
  46. /*********************************************************************\
  47.     Config - finds the MIO board and sets it up.  Returns 1 if
  48.         successful.
  49. \*********************************************************************/
  50.  
  51.  
  52. short CMIO::Config(void)
  53. {
  54.     char mode = true32b;
  55.     SpBlock mySpBlock;
  56.     OSErr error;
  57.     unsigned char name[128];
  58.     short slot;
  59.     unsigned char *slotBaseAddr;
  60.     short ctr;
  61.     
  62.     // •• find MIO board ••
  63.     for(slot=0; slot<8; slot++)
  64.     {
  65.         mySpBlock.spSlot=slot+8;
  66.         error=SCkCardStat(&mySpBlock);
  67.         if (error) continue;
  68.         mySpBlock.spID=1;
  69.         mySpBlock.spResult=(long) &name;
  70.         error=SReadDrvrName(&mySpBlock);
  71.         // name is a pascal string, so skip 1st character in conversion
  72.         if (strncmp((char *)name+1, ".NB-MIO-16", 6)==0) break;
  73.     }
  74.     if (slot==8) return 0; // not found
  75.     
  76.     // •• set up register pointers ••
  77.     SwapMMUMode(&mode);
  78.     if(mode)   // check for 32-bit addressing mode
  79.         slotBaseAddr = (unsigned char *) GetBase32Address(slot);
  80.     else // 24-bit mode
  81.         slotBaseAddr = (unsigned char *) GetBase24Address(slot);
  82.     SwapMMUMode(&mode); // restore mode
  83.     
  84.     // Configuration and Status Registers
  85.     comReg1 =         (unsigned short *)(slotBaseAddr + 0x00);
  86.     comReg2 =         (unsigned short *)(slotBaseAddr + 0x04);
  87.     statReg =         (unsigned short *)(slotBaseAddr + 0x00);
  88.     
  89.     // Event Strobe Register Group
  90.     startConvReg =     (unsigned short *)(slotBaseAddr + 0x10);
  91.     startDAQReg =     (unsigned short *)(slotBaseAddr + 0x14);
  92.     ADClearReg =     (unsigned short *)(slotBaseAddr + 0x18);
  93.     exStrobeReg =    (unsigned short *)(slotBaseAddr + 0x1C);
  94.  
  95.     // Analog Output Register Group
  96.     DAC0Reg =         (unsigned short *)(slotBaseAddr + 0x20);
  97.     DAC1Reg =         (unsigned short *)(slotBaseAddr + 0x24);
  98.     DAC01Reg =         (unsigned short *)(slotBaseAddr + 0x28);
  99.     
  100.     // Analog Input Register Group
  101.     MUXCounterReg = (unsigned short *)(slotBaseAddr + 0x08);
  102.     MUXGainReg =    (unsigned short *)(slotBaseAddr + 0x0C);
  103.     ADFIFOReg =        (unsigned short *)(slotBaseAddr + 0x2C);
  104.     
  105.     // Counter/Timer (AM9513) Register Group
  106.     AmDataReg =     (unsigned short *)(slotBaseAddr + 0x30);
  107.     AmCommandReg =     (unsigned short *)(slotBaseAddr + 0x34);
  108.     AmStatusReg =     (unsigned short *)(slotBaseAddr + 0x34);
  109.  
  110.     // •• Reset board (NB-MIO-16 User's Manual page 4-36) ••
  111.     *comReg1 = 0;
  112.     *comReg2 = 0;
  113.     *MUXGainReg = 0;
  114.     *AmCommandReg = 0xFFFF;
  115.     *AmCommandReg = 0xFFEF;
  116.     *AmCommandReg = 0xFF17;
  117.     *AmDataReg = 0xF000;
  118.     for(ctr=1; ctr<=5; ctr++)
  119.     {
  120.         *AmCommandReg = 0xFF00 + ctr;
  121.         *AmDataReg = 0x0004;
  122.         *AmCommandReg = 0xFF08 + ctr;
  123.         *AmDataReg = 0x0003;
  124.     }
  125.     *AmCommandReg = 0xFF5F;
  126.     
  127.     *ADClearReg = 0;
  128.  
  129.     comRegVal = 0;
  130.  
  131.     return 1;
  132. }
  133.  
  134. /*********************************************************************\
  135.     ConfigureCollection -- set up the MIO to do Multiple A/D
  136.         conversions with Channel Scanning
  137.     NB-MIO-16 User's manual page 4-49
  138.     The channelArray is an array of 16 channel numbers (0-15) to sample
  139.         a gain of 1 is used
  140.     sampleInterval is the time between samples in units of 1 µs
  141.         (2-65535)
  142.     nSamples is the number of samples to take
  143. \*********************************************************************/
  144.  
  145. void CMIO::ConfigureCollection(unsigned short *channelArray, unsigned short sampleInterval,
  146.                                unsigned long nSamples)
  147. {
  148.     short i;
  149.     
  150.     // clear before starting
  151.     *ADClearReg = 0;
  152.  
  153.     // •• Set up the analog channel and gain selection sequence ••
  154.     for(i=0; i<15; i++)
  155.     {
  156.         *MUXCounterReg = i;
  157.         *MUXGainReg = channelArray[i];
  158.     }
  159.     *MUXCounterReg = 15;
  160.     *MUXGainReg = channelArray[15] + 0x0010; // from MIO Control App
  161.     
  162.     // •• Program the sample-interval counter ••
  163.     *AmCommandReg = 0xFF03;
  164.     *AmDataReg = 0x8B25; // 1 MHz clock
  165.     *AmCommandReg = 0xFF0B;
  166.     *AmDataReg = 0x0002;
  167.     *AmCommandReg = 0xFF44;
  168.     *AmCommandReg = 0xFFF3;
  169.     *AmCommandReg = 0xFF0B;             // from MIO Control App
  170.     *AmDataReg = sampleInterval;
  171.     *AmCommandReg = 0xFFF3;             // from MIO Control App
  172.     *AmCommandReg = 0xFFF3;             // from MIO Control App
  173.     *AmCommandReg = 0xFF24;
  174.     
  175.     // •• Program the sample counter ••
  176.     if (nSamples<=65536)
  177.     {
  178.         if (nSamples==65536) nSamples = 0;
  179.         *AmCommandReg = 0xFF04;
  180.         *AmDataReg = 0x1021;
  181.         *AmCommandReg = 0xFF0C;
  182.         *AmDataReg = (unsigned short)nSamples;
  183.         *AmCommandReg = 0xFF68;
  184.         comRegVal = 0;
  185.     }
  186.     else
  187.     {
  188.         *AmCommandReg = 0xFF04;
  189.         *AmDataReg = 0x1001;
  190.         *AmCommandReg = 0xFF0C;
  191.         *AmDataReg = nSamples & 0xFFFFL;
  192.         *AmCommandReg = 0xFF48;
  193.         *AmDataReg = 0x0000;
  194.         *AmCommandReg = 0xFF28;
  195.         *AmCommandReg = 0xFF05;
  196.         *AmDataReg = 0x0001;
  197.         *AmCommandReg = 0xFF0D;
  198.         *AmDataReg = (nSamples >> 16) + 1;
  199.         *AmCommandReg = 0xFF70;
  200.         comRegVal = k1632CNT;
  201.     }
  202.     // •• Clear the A/D circuitry and reset the mux counter ••
  203.     *ADClearReg = 0;
  204.     *MUXCounterReg = 0;
  205.     
  206. }
  207.  
  208. /*********************************************************************\
  209.     StartCollection - start collecting data.  Call after calling
  210.         ConfigureCollection()
  211. \*********************************************************************/
  212.  
  213. void CMIO::StartCollection(void)
  214. {
  215.     // enable scanning
  216.     comRegVal |= kDAQEN;
  217.     comRegVal |= kSCANEN;
  218.     *comReg1 = comRegVal;
  219.     // start scanning
  220.     *startDAQReg = 0;
  221. }
  222.  
  223. /*********************************************************************\
  224.     SampleAvailable - returns true if a sample is available
  225.         Also checks for an error in the status register.
  226.         Check (error & kErrOverflow) and (error & kErrOverrun)
  227.         (both can be set)
  228. \*********************************************************************/
  229.  
  230. short CMIO::SampleAvailable(short *error)
  231. {
  232.     short status;
  233.     
  234.     status = *statReg;
  235.     *error = status & (kErrOverrun + kErrOverflow);
  236.     
  237.     return (status & kCONVAVAIL);
  238. }
  239.  
  240. /*********************************************************************\
  241.     EndCollection - resets clocks after collection
  242. \*********************************************************************/
  243.  
  244. void CMIO::EndCollection(void)
  245. {
  246.     // •• Reset counter 3
  247.     *AmCommandReg = 0xFFC4;
  248.     *AmCommandReg = 0xFF03;
  249.     *AmDataReg = 0x0004;
  250.     *AmCommandReg = 0xFF0B;
  251.     *AmDataReg = 0x0003;
  252.     *AmCommandReg = 0xFF44;
  253.     *AmCommandReg = 0xFF44;
  254.  
  255.     // •• Reset counter 4
  256.     *AmCommandReg = 0xFFC8;
  257.     *AmCommandReg = 0xFF04;
  258.     *AmDataReg = 0x0004;
  259.     *AmCommandReg = 0xFF0C;
  260.     *AmDataReg = 0x0003;
  261.     *AmCommandReg = 0xFF48;
  262.     *AmCommandReg = 0xFF48;
  263.  
  264.     // •• Reset counter 3
  265.     *AmCommandReg = 0xFFD0;
  266.     *AmCommandReg = 0xFF05;
  267.     *AmDataReg = 0x0004;
  268.     *AmCommandReg = 0xFF0D;
  269.     *AmDataReg = 0x0003;
  270.     *AmCommandReg = 0xFF50;
  271.     *AmCommandReg = 0xFF50;
  272.     
  273.     *ADClearReg = 0;
  274.     
  275.     comRegVal = 0;
  276. }
  277.